﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WTwitter.Model.Framework;
using WTwitter.Model.Twitter;

namespace WTwitter.ViewModel {
	/// <summary>
	/// 複数のTimelineViewModelで生成されたTimelineItemViewModelを
	/// 他で再利用できるようにキャッシュを保持しておくクラス
	/// あるTimelineViewModelに含まれるTimelineItemViewModelが必ずしもこのクラスに保持されているとは限らないの注意
	/// </summary>
	sealed class TimelineItemVMCache {
		#region private member
		private static TimelineItemVMCache _instance = new TimelineItemVMCache();
		private List<TimelineItemViewModel> _items = new List<TimelineItemViewModel>();
		private readonly long MaxItemNum = 1000;
		#endregion

		#region Constructor
		private TimelineItemVMCache() {
		}
		#endregion

		#region Property
		/// <summary>
		/// シングルトンのインスタンス
		/// </summary>
		public static TimelineItemVMCache Instance {
			get { return _instance; }
		}
		#endregion

		#region Public Method

		/// <summary>
		/// キャッシュにアイテムを追加する
		/// </summary>
		/// <param name="item">追加するアイテム</param>
		public void Add(TimelineItemViewModel item) {
			if (_items.Contains(item)) {
				return;
			}

			_items.Add(item);

			if (_items.Count > MaxItemNum) {
				_items.RemoveAt(0);
			}
		}

		/// <summary>
		/// キャッシュにアイテムが含まれるかどうかを調べる
		/// </summary>
		/// <param name="item"></param>
		/// <returns></returns>
		public bool Contains(TimelineItemViewModel item) {
			return _items.Contains(item);
		}

		/// <summary>
		/// 返答関係をたどって一連の会話を抽出する
		/// </summary>
		/// <param name="target">起点となるアイテム</param>
		/// <returns>一連のTimelineItemViewModel。引数target自身を含む</returns>
		public IEnumerable<TimelineItemViewModel> GetSequenceOfConversation(TimelineItemViewModel target) {
			TimelineItemViewModel result = null;
			TimelineItemViewModel next = target;

			yield return target;
			do {
				result = GetParentOfConversation(next);
				if (result != null) {
					yield return result;
				}
				next = result;
			} while (result != null);
		}

		/// <summary>
		/// 返答関係にあるアイテムの、元発言の方のアイテムを取得する
		/// </summary>
		/// <param name="target">調べたいアイテム</param>
		/// <returns>targetがあるアイテムの返答である場合には、そのアイテムを返す。targetが返答でない場合はnullを返す</returns>
		public TimelineItemViewModel GetParentOfConversation(TimelineItemViewModel target) {
			if (target.InReplyTo == null) {
				return null;
			}

			return _items.FirstOrDefault(
				item => (target.TypeOfSourceTimeline == item.TypeOfSourceTimeline && target.InReplyTo == item.Id)
				);
		}

		/// <summary>
		/// 指定したユーザーのすべてのアイテム（発言）を取得
		/// </summary>
		/// <param name="userName">取得したいユーザーの名前</param>
		/// <returns></returns>
		public IEnumerable<TimelineItemViewModel> GetAllItemsOf(string userName) {
			foreach (var item in _items) {
				if (item.Name == userName) {
					yield return item;
				}
			}
		}
		#endregion

	}
}
